﻿using System;
using System.Web;
using System.Collections.Generic;
using System.Diagnostics;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Collections.ObjectModel;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using System.Collections.Specialized;
using BdcAdmin = Microsoft.SharePoint.BusinessData.Administration;
using Microsoft.Office.Server.Utilities;
using Microsoft.BusinessData;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.BusinessData.Administration;
using Microsoft.SharePoint.BusinessData.SharedService;
using Microsoft.SharePoint.BusinessData.MetadataModel;

namespace InstanceSiteVSTemplateWizard
{
    public partial class EntityCenterInputForm : Form
    {

        public string entityNameproperty;
        public string entityNameSpaceproperty;
        public string lobSystempInstanceroperty;
        public string specificFinderproperty = null;
        public string Finderproperty = null;
        public NameValueCollection fields;
        public static string spportalName = Program.URL;      
        public string[] entityNames;
        public string webPartType;
        public EntityDetailsInputForm detailsInputForm=null;
        public string AssociatedentityNameproperty = null;
        public string downloadMethodName = null;
       

        public enum WebpartTypeCodes
        {
            BusinessDataItem,
            BusinessDataRelatedList,
            RelatedDocumentList,
            BusinessDataActions,
            BusinessDataList
            
        }
        public WebpartTypeCodes webpartTypeCode;

      
        public EntityCenterInputForm(string[] EntityNames, int j)
        {
            InitializeComponent();            
            entityNames = EntityNames;
            LoadValuesIntoWebPartTypeCombobox(j);
        }

        /* we are using same form for different webparts 
         * if form is used for business data item, then we need to populate specific finder value, 
         * we want to show fields for the specific finder method.
         * if form is used for related documents, then we need to populate download method value */
         
     private void nextButton_Click(object sender, EventArgs e)
        {
            
            string methodName;
          

            entityNameproperty = entityNameComboBox.SelectedItem.ToString();
            entityNameSpaceproperty = comboBox2.SelectedItem.ToString();
            lobSystempInstanceroperty = comboBox3.SelectedItem.ToString();

            if (webpartTypeCode != WebpartTypeCodes.BusinessDataActions)
                Finderproperty = methodNameComboBox.SelectedItem.ToString();
            else
            {
                detailsInputForm = null;              
                this.Close();
                return;

            }

            if (webpartTypeCode == WebpartTypeCodes.BusinessDataItem)
            {
                methodName = specificFinderproperty;
                specificFinderproperty = getSpecificFinderValue(entityNameproperty, entityNameSpaceproperty);
            }
            else
            {
                   methodName = Finderproperty;

            }

            if (webpartTypeCode == WebpartTypeCodes.RelatedDocumentList)
                downloadMethodName = getDownloadMethodName(entityNameproperty, entityNameSpaceproperty);

           
            fields = InitializeEntityFields(entityNameproperty, entityNameSpaceproperty, Finderproperty);
            detailsInputForm = new EntityDetailsInputForm(fields);

            AssociatedentityNameproperty = getAssociatedEntity(entityNameproperty, entityNames);
            this.Hide();
            detailsInputForm.Show();

        }

     internal AdministrationMetadataCatalog GetAdministrationMetadataCatalog(SPServiceContext serviceContext)
        {
            
            AdministrationMetadataCatalog result = null;

            BdcService bdcService = SPFarm.Local.Services.GetValue<BdcService>(String.Empty);
            if (bdcService != null)
            {
                result = bdcService.GetAdministrationMetadataCatalog(serviceContext);
            }

            return result;

        }

     // get the fields in the givend method(finder/specific finder/association */
     internal NameValueCollection InitializeEntityFields(string en, string ens, string f)
        {
            NameValueCollection result = new NameValueCollection();

            string entityName = en;
            string entityNamespace = ens;
            string methodName = f;
            BdcAdmin.AdministrationMetadataCatalog catalog;

            SPSite spSite = new SPSite(spportalName);
            catalog = GetAdministrationMetadataCatalog(SPServiceContext.GetContext((spSite)));
            BdcAdmin.Entity entity = null;
            entity = catalog.GetEntity(entityNamespace, entityName);

            BdcAdmin.MethodInstanceCollection miCollection;
         
            if (webpartTypeCode == WebpartTypeCodes.BusinessDataItem)
                miCollection = entity.GetMethodInstances(Microsoft.BusinessData.MetadataModel.MethodInstanceType.SpecificFinder);
            else if (webpartTypeCode == WebpartTypeCodes.BusinessDataList)
                miCollection = entity.GetMethodInstances(Microsoft.BusinessData.MetadataModel.MethodInstanceType.Finder);
            else if (webpartTypeCode == WebpartTypeCodes.BusinessDataRelatedList)
                miCollection = entity.GetMethodInstances(Microsoft.BusinessData.MetadataModel.MethodInstanceType.AssociationNavigator);
            else if (webpartTypeCode == WebpartTypeCodes.RelatedDocumentList)
                miCollection = entity.GetMethodInstances(Microsoft.BusinessData.MetadataModel.MethodInstanceType.AssociationNavigator);
            else
                miCollection = null;

            BdcAdmin.MethodInstance Finder = null;
            foreach (BdcAdmin.MethodInstance mi in miCollection)
            {
                if (mi.Name == methodName)
                {
                    Finder = mi;
                    break;
                }
            }

            foreach (Microsoft.SharePoint.BusinessData.Administration.TypeDescriptor td in Finder.ReturnTypeDescriptor.ChildTypeDescriptors)
            {
                BuildRecursive(td, td.Name, result);
            }

            return result;
        }


     private void BuildRecursive(BdcAdmin.TypeDescriptor td, string fieldPath, NameValueCollection result)
        {
            bool hasChild = false;
            foreach (BdcAdmin.TypeDescriptor tdChild in td.ChildTypeDescriptors)
            {
                hasChild = true;             
                BuildRecursive(tdChild, tdChild.Name, result);
            }

            if (!hasChild)
                result.Add(fieldPath, td.TypeName);

        }      
       
    /* user selected the entity name, so we want to populate other combobox values */
     private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            EntityCollection result;
            comboBox2.Items.Clear();
            comboBox3.Items.Clear();           
            methodNameComboBox.Items.Clear();

            BdcAdmin.AdministrationMetadataCatalog catalog;

            SPSite spSite = new SPSite(spportalName);
            catalog = GetAdministrationMetadataCatalog(SPServiceContext.GetContext((spSite)));
            string entityname = entityNameComboBox.SelectedItem.ToString();

            result = catalog.GetEntities("*", entityname, true);
            foreach (BdcAdmin.Entity ent in result)
            {
                comboBox2.Items.Add(ent.Namespace);
                BdcAdmin.LobSystem ls = ent.LobSystem;
                foreach (BdcAdmin.LobSystemInstance lsi in ls.LobSystemInstances)
                {
                    comboBox3.Items.Add(lsi.Name);
                }

                BdcAdmin.MethodInstanceCollection miCollection;

                if (webpartTypeCode == WebpartTypeCodes.BusinessDataItem)
                    miCollection = ent.GetMethodInstances(Microsoft.BusinessData.MetadataModel.MethodInstanceType.SpecificFinder);
                else if (webpartTypeCode == WebpartTypeCodes.BusinessDataList)
                    miCollection = ent.GetMethodInstances(Microsoft.BusinessData.MetadataModel.MethodInstanceType.Finder);
                else if (webpartTypeCode == WebpartTypeCodes.BusinessDataRelatedList)
                    miCollection = ent.GetMethodInstances(Microsoft.BusinessData.MetadataModel.MethodInstanceType.AssociationNavigator);
                else if (webpartTypeCode == WebpartTypeCodes.RelatedDocumentList)
                    miCollection = ent.GetMethodInstances(Microsoft.BusinessData.MetadataModel.MethodInstanceType.AssociationNavigator);
                else
                    break;

                foreach (BdcAdmin.MethodInstance mi in miCollection)
                {
                    methodNameComboBox.Items.Add(mi.Name);

                }
            }
            if (comboBox2.Items.Count > 0)
                comboBox2.SelectedIndex = 0;
            else
                comboBox2.ResetText();

            if (comboBox3.Items.Count > 0)
                comboBox3.SelectedIndex = 0;
            else
                comboBox3.ResetText();
         
            if (methodNameComboBox.Items.Count > 0)
                methodNameComboBox.SelectedIndex = 0;
            else
                methodNameComboBox.ResetText();
            
            
        }

        // returns the specific finder method name for given entity 
     private string  getSpecificFinderValue(string en, string ens)
    {
        BdcAdmin.AdministrationMetadataCatalog catalog;
        EntityCollection result;
        string specificFinderName = null;

            SPSite spSite = new SPSite(spportalName);
            catalog = GetAdministrationMetadataCatalog(SPServiceContext.GetContext((spSite)));          

            result = catalog.GetEntities(ens, en, true);
            foreach (BdcAdmin.Entity ent in result)
            {
               

                BdcAdmin.MethodInstanceCollection miCollection;
               
                 miCollection = ent.GetMethodInstances(Microsoft.BusinessData.MetadataModel.MethodInstanceType.SpecificFinder);

                foreach (BdcAdmin.MethodInstance mi in miCollection)
                {
                    specificFinderName = mi.Name;
                    break;

                }
            }
            return specificFinderName;

    }

     // returns the Download method name for given document entity 
     private string getDownloadMethodName(string en, string ens)
     {
         BdcAdmin.AdministrationMetadataCatalog catalog;
         EntityCollection result;
         string downloadMehtodName = null;

         SPSite spSite = new SPSite(spportalName);
         catalog = GetAdministrationMetadataCatalog(SPServiceContext.GetContext((spSite)));

         result = catalog.GetEntities(ens, en, true);
         foreach (BdcAdmin.Entity ent in result)
         {


             BdcAdmin.MethodInstanceCollection miCollection;

             miCollection = ent.GetMethodInstances(Microsoft.BusinessData.MetadataModel.MethodInstanceType.GenericInvoker);

             foreach (BdcAdmin.MethodInstance mi in miCollection)
             {
                 downloadMehtodName = mi.Name;
                 break;

             }
         }
         return downloadMehtodName;

     }

    // load the values in webpart type comboBox
     private void LoadValuesIntoWebPartTypeCombobox(int index)
        {
            webPartTypeCombobox.Items.Clear();
            webPartTypeCombobox.Items.Add("Business Data Item");
            webPartTypeCombobox.Items.Add("Business Data Related List");
            webPartTypeCombobox.Items.Add("Related Document List");
            webPartTypeCombobox.Items.Add("Business Data Actions");                   
            webPartTypeCombobox.Items.Add("Business Data List");
          
            if (index < 3)
            {
                webPartTypeCombobox.SelectedIndex = index;
                webPartTypeCombobox.Enabled = false;
            }
            else
                webPartTypeCombobox.Enabled = true;
            
         
        }
     
     // returns the all entities which have association method 
     private void getAllCenterEntities()
        {
            entityNameComboBox.Items.Clear();
            try
            {

                EntityCollection result;

                BdcAdmin.AdministrationMetadataCatalog catalog;

                SPSite spSite = new SPSite(spportalName);
                catalog = GetAdministrationMetadataCatalog(SPServiceContext.GetContext((spSite)));

                result = catalog.GetEntities("*", "*", true);
                foreach (BdcAdmin.Entity ent in result)
                {

                    bool isEntityHaveAssociations = false;
                        AssociationCollection assCollection = ent.AssociationsWithEntityAsSource;
                        foreach (BdcAdmin.Association ass1 in assCollection)
                        {
                            isEntityHaveAssociations = true;
                        }

                        if (isEntityHaveAssociations)
                        entityNameComboBox.Items.Add(ent.Name);

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }         
        }

     // returns the all entities 
     private void getAllIndependentEntities()
      {
            entityNameComboBox.Items.Clear();
            try
            {

                EntityCollection result;

                BdcAdmin.AdministrationMetadataCatalog catalog;

                SPSite spSite = new SPSite(spportalName);
                catalog = GetAdministrationMetadataCatalog(SPServiceContext.GetContext((spSite)));

                result = catalog.GetEntities("*", "*", true);
                foreach (BdcAdmin.Entity ent in result)
                {
                     entityNameComboBox.Items.Add(ent.Name);

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }         
        }

    // return true if the entites are associated other wise false
    public bool isAssociatedEntities(string entityName1, string entityName2)
        {
            EntityCollection result;

            BdcAdmin.AdministrationMetadataCatalog catalog;

            SPSite spSite = new SPSite(spportalName);
            catalog = GetAdministrationMetadataCatalog(SPServiceContext.GetContext((spSite)));

            result = catalog.GetEntities("*", entityName1, true);
            foreach (BdcAdmin.Entity ent in result)
            {

                AssociationCollection assCollection = ent.AssociationsWithEntityAsSource;
                foreach (BdcAdmin.Association ass1 in assCollection)
                {
                    BdcAdmin.EntityReference entref = ass1.DestinationEntityReference;
                    if (entref.Name.CompareTo(entityName2) == 0)
                        return true;
                    break;

                }

            }
            return false;
        }

        // return the associated entity for given entity
        // associated entity should be part for entityNames1 list
    private string getAssociatedEntity(string entityName, string[] entityNames1)
        {
            EntityCollection result;

            BdcAdmin.AdministrationMetadataCatalog catalog;

            SPSite spSite = new SPSite(spportalName);
            catalog = GetAdministrationMetadataCatalog(SPServiceContext.GetContext((spSite)));

            for (int i = 0; i < entityNames1.Length; i++)
            {
                if (entityNames1[i] == null)
                    return null;

                result = catalog.GetEntities("*", entityNames1[i], true);

            foreach (BdcAdmin.Entity ent in result)
            {

                AssociationCollection assCollection = ent.AssociationsWithEntityAsSource;
                foreach (BdcAdmin.Association ass1 in assCollection)
                {
                    BdcAdmin.EntityReference entref = ass1.DestinationEntityReference;


                    if (entref.Name.CompareTo(entityName.ToString()) == 0)
                        return entityNames1[i];
                  
                }

            }
            }
            return null;
        }

    /* return the all associated entities for given entities
     * this method will be called when ISV selected the relted list webpart or related document webpart */
    private void getAllAssociatedEntities(string[] entityNames)
        {
           entityNameComboBox.Items.Clear();
           foreach(string entityName in entityNames)
           {

               if (entityName == null)
                   continue;

                EntityCollection result;

                BdcAdmin.AdministrationMetadataCatalog catalog;

                SPSite spSite = new SPSite(spportalName);
                catalog = GetAdministrationMetadataCatalog(SPServiceContext.GetContext((spSite)));

                result = catalog.GetEntities("*", entityName, true);
                foreach (BdcAdmin.Entity ent in result)
                {
                    
                    AssociationCollection assCollection = ent.AssociationsWithEntityAsSource;
                    foreach (BdcAdmin.Association ass1 in assCollection)
                    {
                        BdcAdmin.EntityReference entref = ass1.DestinationEntityReference;
                        entityNameComboBox.Items.Add(entref.Name);

                    }                 
                    
                }
           }
          
        }
     

            //webPartTypeCombobox.Items.Add("Business Data Item");
            //webPartTypeCombobox.Items.Add("Business Data Related List");
            //webPartTypeCombobox.Items.Add("Business Data Actions");                   
            //webPartTypeCombobox.Items.Add("Business Data List");
         
     /* this method will be called when ISV selects the webpart type.
      * Depending upon selection, we want to show corresponding information to ISV */

     private void webPartTypeCombobox_SelectedIndexChanged(object sender, EventArgs e)
        {
            comboBox2.Items.Clear();
            comboBox3.Items.Clear();
            methodNameComboBox.Items.Clear();

           switch( webPartTypeCombobox.SelectedIndex )
           {
               case 0:
                   webpartTypeCode = WebpartTypeCodes.BusinessDataItem;
                   label5.Text = "Specific Finder";                   
                   label5.Visible = true;
                   methodNameComboBox.Visible = true;
                   comboBox2.Items.Clear();
                   comboBox3.Items.Clear();           
                   methodNameComboBox.Items.Clear();
                   checkBox1.Visible = true;
                   checkBox1.Text = "Overwrite instane Site template Name in BDC Model";
                   getAllCenterEntities();                  
                   break;

               case 1:
                   webpartTypeCode = WebpartTypeCodes.BusinessDataRelatedList;
                   label5.Text = "Association Navigator";                   
                   label5.Visible = true;
                   methodNameComboBox.Visible = true;
                   comboBox2.Items.Clear();
                   comboBox3.Items.Clear();           
                   methodNameComboBox.Items.Clear();
                   checkBox1.Visible = false;
                   getAllAssociatedEntities(entityNames);                   
                   break;
               case 2:
                   webpartTypeCode = WebpartTypeCodes.RelatedDocumentList;
                   label5.Text = "Association Navigator";
                   label5.Visible = true;
                   methodNameComboBox.Visible = true;
                   comboBox2.Items.Clear();
                   comboBox3.Items.Clear();
                   methodNameComboBox.Items.Clear();
                   checkBox1.Visible = false;
                   getAllAssociatedEntities(entityNames);
                   break;
               case 3:
                   webpartTypeCode = WebpartTypeCodes.BusinessDataActions;
                   label5.Visible = false;
                   methodNameComboBox.Visible = false;
                   comboBox2.Items.Clear();
                   comboBox3.Items.Clear();           
                   methodNameComboBox.Items.Clear();                   
                   checkBox1.Visible = true;
                   checkBox1.Text = "Do you Want add one more WebPart?";
                   checkBox1.Checked = true;
                   getAllCenterEntities();
                   break;

               case 4: 
                   webpartTypeCode = WebpartTypeCodes.BusinessDataList;
                   label5.Text = "Finder";
                   label5.Visible = true;
                   methodNameComboBox.Visible = true;
                   comboBox2.Items.Clear();
                   comboBox3.Items.Clear();           
                   methodNameComboBox.Items.Clear();
                   checkBox1.Visible = false;
                   getAllIndependentEntities();                   
                   break;
           
           }
            
               
        }

       
  

 }
}
